package com.umeox.watch.moto.apiclient.http;

import android.util.Log;

import com.alibaba.fastjson.JSONObject;
import com.umeox.moto.common.utils.DateUtils;
import com.umeox.watch.moto.apiclient.http.callback.TokenChangedListener;
import com.umeox.watch.moto.apiclient.http.callback.WaasCallback;
import com.umeox.watch.moto.apiclient.http.client.APIClientFactory;
import com.umeox.watch.moto.apiclient.http.client.APIClientImpl;
import com.umeox.watch.moto.apiclient.http.request.WaasRequest;
import com.umeox.watch.moto.apiclient.http.response.WaasResponse;
import com.umeox.watch.moto.apiclient.model.GalleryDTO;
import com.umeox.watch.moto.apiclient.model.LocationDTO;
import com.umeox.watch.moto.apiclient.model.TokenDTO;
import com.umeox.watch.moto.apiclient.utils.GsonUtils;

import org.json.JSONException;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class WaasApiWrapper extends BaseApi {

    private TokenChangedListener tokenChangedListener;
    private HostRedirect redirectImpl;

    private WaasApiWrapper() {
    }

    public static WaasApiWrapper getInstance() {
        return InstanceHolder.INSTANCE;
    }

    public void init(APIClientImpl.InitializeConfig config) {
        if (InstanceHolder.initialized) {
            throw new RuntimeException("can not duplicated initialize !");
        } else {
            super.init(config.appKey, config.appSecret, config.accessToken);
            TokenInterceptor interceptor = new TokenInterceptor();
            if (config.interceptors == null || !config.interceptors.contains(interceptor)) {
                config.addInterceptor(interceptor);
            }
            apiClient = (APIClientImpl) APIClientFactory.getApiClient();
            apiClient.init(config);

            InstanceHolder.initialized = true;
        }
    }

    public void setTokenChangedLisenter(TokenChangedListener tokenChangedListener) {
        this.tokenChangedListener = tokenChangedListener;
    }

    public void setHostRedirect(HostRedirect hostRedirect) {
        this.redirectImpl = hostRedirect;
    }

    @Override
    protected String getHost(ApiEnum apiEnum) {
        return redirectImpl != null ? redirectImpl.getHost(apiEnum) : "";
    }

    private void checkInitialize() {
        if (!InstanceHolder.initialized) {
            throw new RuntimeException("initialize first");
        }
    }

    public TokenDTO refreshToken() {
        checkInitialize();
        Map<String, Object> param = new HashMap<String, Object>();
        param.put("client_id", clientID);
        param.put("client_secret", clientSecret);
        param.put("grant_type", "client_credentials");
        WaasResponse response = sendSyncRequest(ApiEnum.ACCESS_TOKEN, param);
        if (response.isSuccessful()) {
            TokenDTO result = (TokenDTO) response.getData();
            if (result != null) {
                accessToken = result.access_token == null ? "" : result.access_token;
                if (tokenChangedListener != null) {
                    tokenChangedListener.onTokenRefresh(accessToken);
                }
                return result;
            }
        }
        //throw new SdkException("refresh token fail:" + response.getMessage());
        return null;
    }

    public void refreshToken(int count, final WaasCallback callback) {
        checkInitialize();
        Map<String, Object> param = new HashMap<>();
        param.put("client_id", clientID);
        param.put("client_secret", clientSecret);
        param.put("grant_type", "client_credentials");
        param.put("count", count);
        sendAsyncRequest(ApiEnum.ACCESS_TOKEN, param, new WaasCallback() {
            @Override
            public void onFailure(WaasRequest request, Exception e) {
                callback.onFailure(request, e);
            }

            @Override
            public void onResponse(WaasRequest request, WaasResponse response) {
                if (response.isSuccessful()) {
                    TokenDTO result = (TokenDTO) response.getData();
                    if (result != null) {
                        accessToken = result.access_token == null ? "" : result.access_token;
                        if (tokenChangedListener != null) {
                            tokenChangedListener.onTokenRefresh(accessToken);
                        }
                    }
                }
                callback.onResponse(request, response);
            }
        });
    }

    public void initServerConfig(String deviceId, WaasCallback callback) {
        checkInitialize();
        Map<String, Object> param = new HashMap<String, Object>();
        param.put("deviceId", deviceId);
        sendAsyncRequest(ApiEnum.INIT_SERVER_CONFIG, param, callback);
    }

    public WaasResponse initServerConfig(String deviceId) {
        checkInitialize();
        Map<String, Object> param = new HashMap<String, Object>();
        param.put("deviceId", deviceId);
        return sendSyncRequest(ApiEnum.INIT_SERVER_CONFIG, param);
    }



    public void getClassTime(String deviceId, WaasCallback callback) {
        checkInitialize();
        Map<String, Object> param = new HashMap<String, Object>();
        param.put("deviceId", deviceId);
        sendAsyncRequest(ApiEnum.REFRESH_CLASSTIME, param, callback);
    }

    public WaasResponse getClassTime(String deviceId) {
        checkInitialize();
        Map<String, Object> param = new HashMap<String, Object>();
        param.put("deviceId", deviceId);
        return sendSyncRequest(ApiEnum.REFRESH_CLASSTIME, param);
    }

    public WaasResponse getMultipleClassTime(String deviceId) {
        checkInitialize();
        Map<String, Object> param = new HashMap<String, Object>();
        param.put("deviceId", deviceId);
        return sendSyncRequest(ApiEnum.REFRESH_MULTIPLE_CLASSTIME, param);
    }

    public void getConcernTime(String deviceId, WaasCallback callback) {
        checkInitialize();
        Map<String, Object> param = new HashMap<String, Object>();
        param.put("deviceId", deviceId);
        sendAsyncRequest(ApiEnum.REFRESH_CONCERNTIME, param, callback);
    }

    public WaasResponse getConcernTime(String deviceId) {
        checkInitialize();
        Map<String, Object> param = new HashMap<String, Object>();
        param.put("deviceId", deviceId);
        return sendSyncRequest(ApiEnum.REFRESH_CONCERNTIME, param);
    }

    public void getAlarmList(String deviceId, WaasCallback callback) {
        Map<String, Object> param = new HashMap<String, Object>();
        param.put("deviceId", deviceId);
        sendAsyncRequest(ApiEnum.REFRESH_ALARMLIST, param, callback);
    }

    public WaasResponse getAlarmList(String deviceId) {
        Map<String, Object> param = new HashMap<String, Object>();
        param.put("deviceId", deviceId);
        return sendSyncRequest(ApiEnum.REFRESH_ALARMLIST, param);
    }

    public void getContactList(String deviceId, WaasCallback callback) {
        checkInitialize();
        Map<String, Object> param = new HashMap<String, Object>();
        param.put("deviceId", deviceId);
        sendAsyncRequest(ApiEnum.GET_CONTACTS, param, callback);
    }

    public WaasResponse getContactList(String deviceId) {
        checkInitialize();
        Map<String, Object> param = new HashMap<String, Object>();
        param.put("deviceId", deviceId);
        return sendSyncRequest(ApiEnum.GET_CONTACTS, param);
    }

    public void makeFriend(String deviceId, String selfMac, String[] nearByMacs, WaasCallback callback) {
        Map<String, Object> param = new HashMap<String, Object>();
        param.put("deviceId", deviceId);
        param.put("selfMac", selfMac);
        param.put("nearByMacs", nearByMacs);
        sendAsyncRequest(ApiEnum.MAKE_FRIEND, param, callback);
    }

    public WaasResponse makeFriend(String deviceId, String selfMac, String[] nearByMacs) {
        checkInitialize();
        Map<String, Object> param = new HashMap<String, Object>();
        param.put("deviceId", deviceId);
        param.put("selfMac", selfMac);
        param.put("nearByMacs", Arrays.asList(nearByMacs));
        return sendSyncRequest(ApiEnum.MAKE_FRIEND, param);
    }

//    private static List<String> convertNearByMacs(String[] nearByMacs) {
//        List<String> wifiList = new ArrayList<>();
//
//        wifiList.addAll(Arrays.asList(nearByMacs));
//
//        return wifiList;
//    }

    public void getBuddies(String deviceId, WaasCallback callback) {
        checkInitialize();
        Map<String, Object> param = new HashMap<String, Object>();
        param.put("deviceId", deviceId);
        sendAsyncRequest(ApiEnum.GET_BUDDIES, param, callback);
    }

    public WaasResponse getBuddies(String deviceId) {
        checkInitialize();
        Map<String, Object> param = new HashMap<String, Object>();
        param.put("deviceId", deviceId);
        return sendSyncRequest(ApiEnum.GET_BUDDIES, param);
    }

    public void uploadStep(String deviceId, int stepCount, WaasCallback callback) {
        checkInitialize();
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("deviceId", deviceId);
        params.put("reportTime", DateUtils.formatDateTime(System.currentTimeMillis(), "yyMMddHHmmss"));
        params.put("stepCount", stepCount);
        sendAsyncRequest(ApiEnum.UPLOAD_STEP, params, callback);
    }

    public void uploadHeartRate(String deviceId, long date,long startTime,long endTime,int heartRate,int minHeartRate,int maxHeartRate, WaasCallback callback) {
        checkInitialize();
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("deviceId", deviceId);
        params.put("date", date);
        params.put("startTime", startTime);
        params.put("endTime", endTime);
        params.put("heartRate", heartRate);
        params.put("minHeartRate", minHeartRate);
        params.put("maxHeartRate", maxHeartRate);
        sendAsyncRequest(ApiEnum.UPLOAD_HEART_RATE, params, callback);
    }

    public WaasResponse uploadStep(String deviceId, int stepCount) {
        checkInitialize();
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("deviceId", deviceId);
        params.put("reportTime", DateUtils.formatDateTime(System.currentTimeMillis(), "yyMMddHHmmss"));
        params.put("stepCount", stepCount);
        return sendSyncRequest(ApiEnum.UPLOAD_STEP, params);
    }
    public void uploadAudioTypes(String deviceId, String audioType,WaasCallback callback) {
        checkInitialize();
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("deviceId", deviceId);
        params.put("audioTypes", audioType);
        sendAsyncRequest(ApiEnum.UPLOAD_AudioTypes, params,callback);
    }
    public void uploadLocation(String deviceId, WaasCallback callback, LocationDTO locationDTO) {
        checkInitialize();
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("deviceId", deviceId);
        params.put("reportReason", locationDTO.reportReason);
        params.put("reportReasonAttr", locationDTO.reportReasonAttr);
        params.put("reportTime", locationDTO.reportTime);
        params.put("locationMode", locationDTO.locationMode);
        params.put("lat", locationDTO.lat);
        params.put("lng", locationDTO.lng);
        params.put("address", locationDTO.address);
        params.put("accuracy", locationDTO.accuracy);
        params.put("mcc", String.valueOf(locationDTO.mcc));
        params.put("mnc", locationDTO.mnc);
        params.put("stepCount", locationDTO.stepCount);
        params.put("batteryVal", locationDTO.batteryVal);
        params.put("cellTower", locationDTO.cellTower);
        params.put("nearByCellTowers", locationDTO.nearByCellTowers);
        params.put("wifiPoints", locationDTO.wifiPointsList);
        params.put("network", locationDTO.network);
        params.put("locMethod", locationDTO.locMethod);
        sendAsyncRequest(ApiEnum.UPLOAD_LOCATION, params, callback);
    }

    public WaasResponse uploadLocation(String deviceId, LocationDTO locationDTO) {
        checkInitialize();
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("deviceId", deviceId);
        params.put("reportReason", locationDTO.reportReason);
        params.put("reportReasonAttr", locationDTO.reportReasonAttr);
        params.put("reportTime", locationDTO.reportTime);
        params.put("locationMode", locationDTO.locationMode);
        params.put("lat", locationDTO.lat);
        params.put("lng", locationDTO.lng);
        params.put("address", locationDTO.address);
        params.put("accuracy", locationDTO.accuracy);
        params.put("mcc", String.valueOf(locationDTO.mcc));
        params.put("mnc", locationDTO.mnc);
        params.put("stepCount", locationDTO.stepCount);
        params.put("batteryVal", locationDTO.batteryVal);
        params.put("cellTower", locationDTO.cellTower);
        params.put("nearByCellTowers", locationDTO.nearByCellTowers);
        params.put("wifiPoints", locationDTO.wifiPointsList);
        try {
            Log.e("wifiPoints","wifiPoints:" + GsonUtils.objectToArray(locationDTO.wifiPointsList).toString());
        } catch (JSONException e) {
            e.printStackTrace();
        }
        params.put("network", locationDTO.network);
        params.put("locMethod", locationDTO.locMethod);
        return sendSyncRequest(ApiEnum.UPLOAD_LOCATION, params);
    }

    public void uploadSOS(String deviceId, int sosId, String fileId, long times, WaasCallback callback) {
        checkInitialize();
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("deviceId", deviceId);
        params.put("reportTime", DateUtils.formatDateTime(times, "yyMMddHHmmss"));
        params.put("sosId", sosId);
        params.put("fileId", fileId);
        sendAsyncRequest(ApiEnum.UPLOAD_SOS, params, callback);
    }

    public WaasResponse uploadSOS(String deviceId, long sosId, String fileId, long times) {
        checkInitialize();
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("deviceId", deviceId);
        params.put("reportTime", DateUtils.formatDateTime(times, "yyMMddHHmmss"));
        params.put("sosId", sosId);
        params.put("fileId", fileId);
        return sendSyncRequest(ApiEnum.UPLOAD_SOS, params);
    }

    public void getMessageList(String deviceId, String friendId, int msgType, long lastMsgId, WaasCallback callback) {
        checkInitialize();
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("deviceId", deviceId);
        params.put("friendId", friendId);
        params.put("type", msgType);
        params.put("messageId", lastMsgId);
        sendAsyncRequest(ApiEnum.REFRESH_MESSAGE_LIST, params, callback);
    }

    public WaasResponse getMessageList(String deviceId, String friendId, int msgType, long lastMsgId) {
        checkInitialize();
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("deviceId", deviceId);
        params.put("friendId", friendId);
        params.put("type", msgType);
        params.put("messageId", lastMsgId);
        return sendSyncRequest(ApiEnum.REFRESH_MESSAGE_LIST, params);
    }

    public void getMessageList(String deviceId, String friendId, long lastMessageId, WaasCallback callback) {
        checkInitialize();
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("deviceId", deviceId);
        params.put("friendId", friendId);
        params.put("type", 0);
        params.put("messageId", lastMessageId);
        sendAsyncRequest(ApiEnum.REFRESH_MESSAGE_LIST, params, callback);
    }

    public WaasResponse getMessageList(String deviceId, String friendId, long lastMessageId) {
        checkInitialize();
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("deviceId", deviceId);
        params.put("friendId", friendId);
        params.put("type", 0);
        params.put("messageId", lastMessageId);
        return sendSyncRequest(ApiEnum.REFRESH_MESSAGE_LIST, params);
    }

    public void sendMessage(String from, String to, long msgTime, int msgType, String msg, WaasCallback callback) {
        checkInitialize();
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("from", from);
        params.put("to", to);
        params.put("type", 0);
        params.put("msgTime", msgTime);
        params.put("msgType", msgType);
        params.put("msg", msg);
        sendAsyncRequest(ApiEnum.SEND_CHAT_MESSAGE, params, callback);
    }

    public WaasResponse sendMessage(String from, String to, long msgTime, int msgType, String msg) {
        checkInitialize();
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("from", from);
        params.put("to", to);
        params.put("type", 0);
        params.put("msgTime", msgTime);
        params.put("msgType", msgType);
        params.put("msg", msg);
        return sendSyncRequest(ApiEnum.SEND_CHAT_MESSAGE, params);
    }

    public void getPetInfo(String deviceId, WaasCallback callback) {
        checkInitialize();
        Map<String, Object> param = new HashMap<String, Object>();
        param.put("deviceId", deviceId);
        sendAsyncRequest(ApiEnum.GET_PETINFO, param, callback);
    }

    public WaasResponse getPetInfo(String deviceId) {
        checkInitialize();
        Map<String, Object> param = new HashMap<String, Object>();
        param.put("deviceId", deviceId);
        return sendSyncRequest(ApiEnum.GET_PETINFO, param);
    }


    public void uploadAlbum(String deviceId, List<GalleryDTO> list, WaasCallback callback) {
        checkInitialize();
        Map<String, Object> param = new HashMap<String, Object>();
        param.put("deviceId", deviceId);
        param.put("bucket", "wherecom-file-01");
        param.put("region", "eu-west-1");
        if (list != null && !list.isEmpty()) {
            List<JSONObject> temp = new ArrayList<>(list.size());
            for (GalleryDTO dto : list) {
                JSONObject jsonObject = new JSONObject();
                try {
                    jsonObject.put("fileId", dto.imageUrl);
                    jsonObject.put("uploadTime", System.currentTimeMillis());
                    jsonObject.put("fileSize", dto.imageSize);
                    temp.add(jsonObject);
                } catch (Exception ignored) {
                }
            }
            param.put("files", temp);
        }
        sendAsyncRequest(ApiEnum.ALBUM_UPLOAD, param, callback);
    }

    public WaasResponse uploadAlbum(String deviceId, List<GalleryDTO> list) {
        checkInitialize();
        Map<String, Object> param = new HashMap<String, Object>();
        param.put("deviceId", deviceId);
        param.put("bucket", "wherecom-file-01");
        param.put("region", "eu-west-1");
        if (list != null && !list.isEmpty()) {
            List<JSONObject> temp = new ArrayList<>(list.size());
            for (GalleryDTO dto : list) {
                JSONObject jsonObject = new JSONObject();
                try {
                    jsonObject.put("fileId", dto.imageUrl);
                    jsonObject.put("uploadTime", System.currentTimeMillis());
                    jsonObject.put("fileSize", dto.imageSize);
                    temp.add(jsonObject);
                } catch (Exception ignored) {
                }
            }
            param.put("files", temp);
        }
        return sendSyncRequest(ApiEnum.ALBUM_UPLOAD, param);
    }

    /**
     * 邀请加入VOIP通话
     */
    public void inviteJoinVoip(String deviceId, String friendId, String channel, WaasCallback callback) {
        checkInitialize();
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("deviceId", deviceId);
        params.put("friendId", friendId);
        params.put("channel", channel);
        params.put("type", 3);
        sendAsyncRequest(ApiEnum.INVITE_JOIN_VIDEO, params, callback);
    }

    /**
     * 邀请加入VOIP通话
     */
    public WaasResponse inviteJoinVoip(String deviceId, String friendId, String channel) {
        checkInitialize();
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("deviceId", deviceId);
        params.put("friendId", friendId);
        params.put("channel", channel);
        params.put("type", 3);
        return sendSyncRequest(ApiEnum.INVITE_JOIN_VIDEO, params);
    }

    /**
     * 邀请加入视频
     */
    public void inviteJoinVideo(String deviceId, String friendId, String channel, WaasCallback callback) {
        checkInitialize();
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("deviceId", deviceId);
        params.put("friendId", friendId);
        params.put("channel", channel);
        params.put("type", 2);
        sendAsyncRequest(ApiEnum.INVITE_JOIN_VIDEO, params, callback);
    }

    /**
     * 邀请加入视频
     */
    public WaasResponse inviteJoinVideo(String deviceId, String friendId, String channel) {
        checkInitialize();
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("deviceId", deviceId);
        params.put("friendId", friendId);
        params.put("channel", channel);
        params.put("type", 2);
        return sendSyncRequest(ApiEnum.INVITE_JOIN_VIDEO, params);
    }

    /**
     * 通知取消视频
     */
    public void notifyCancelVideo(String deviceId, String friendId, String channel, WaasCallback callback) {
        checkInitialize();
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("deviceId", deviceId);
        params.put("friendId", friendId);
        params.put("channel", channel);
        params.put("type", 2);
        sendAsyncRequest(ApiEnum.NOTIFY_CANCEL_VIDEO, params, callback);
    }

    /**
     * 通知取消视频
     */
    public WaasResponse notifyCancelVideo(String deviceId, String friendId, String channel) {
        checkInitialize();
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("deviceId", deviceId);
        params.put("friendId", friendId);
        params.put("channel", channel);
        params.put("type", 2);
        return sendSyncRequest(ApiEnum.NOTIFY_CANCEL_VIDEO, params);
    }

    /**
     * 通知取消VOIP
     */
    public void notifyCancelVoip(String deviceId, String friendId, String channel, WaasCallback callback) {
        checkInitialize();
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("deviceId", deviceId);
        params.put("friendId", friendId);
        params.put("channel", channel);
        params.put("type", 3);
        sendAsyncRequest(ApiEnum.NOTIFY_CANCEL_VIDEO, params, callback);
    }

    /**
     * 通知取消VOIP
     */
    public WaasResponse notifyCancelVoip(String deviceId, String friendId, String channel) {
        checkInitialize();
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("deviceId", deviceId);
        params.put("friendId", friendId);
        params.put("channel", channel);
        params.put("type", 3);
        return sendSyncRequest(ApiEnum.NOTIFY_CANCEL_VIDEO, params);
    }

    /**
     * 上传视频通话时间
     */
    public void uploadVideoTime(String deviceId, String friendId, String channel, long startTime, long endTime, WaasCallback callback) {
        checkInitialize();
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("deviceId", deviceId);
        params.put("friendId", friendId);
        params.put("startTime", startTime);
        params.put("endTime", endTime);
        params.put("channel", channel);
        sendAsyncRequest(ApiEnum.UPLOAD_VIDEO_TIME, params, callback);
    }

    /**
     * 上传视频通话时间
     */
    public WaasResponse uploadVideoTime(String deviceId, String friendId, String channel, long startTime, long endTime) {
        checkInitialize();
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("deviceId", deviceId);
        params.put("friendId", friendId);
        params.put("startTime", startTime);
        params.put("endTime", endTime);
        params.put("channel", channel);
        return sendSyncRequest(ApiEnum.UPLOAD_VIDEO_TIME, params);
    }

    /**
     * 获取壁纸
     */
    public void getWallpapers(String deviceId, WaasCallback callback) {
        checkInitialize();
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("deviceId", deviceId);
        sendAsyncRequest(ApiEnum.GET_WALLPAPERS, params, callback);
    }

    /**
     * 获取壁纸
     */
    public WaasResponse getWallpapers(String deviceId) {
        checkInitialize();
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("deviceId", deviceId);
        return sendSyncRequest(ApiEnum.GET_WALLPAPERS, params);
    }

    /**
     * 获取wifi
     */
    public void getWifiList(String deviceId, WaasCallback callback) {
        checkInitialize();
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("deviceId", deviceId);
        sendAsyncRequest(ApiEnum.GET_WIFI_LIST, params, callback);
    }

    /**
     * 获取wifi
     */
    public WaasResponse getWifiList(String deviceId) {
        checkInitialize();
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("deviceId", deviceId);
        return sendSyncRequest(ApiEnum.GET_WIFI_LIST, params);
    }

    public interface HostRedirect {
        String getHost(ApiEnum apiEnum);
    }

    private static class InstanceHolder {
        private static final WaasApiWrapper INSTANCE = new WaasApiWrapper();
        private static boolean initialized = false;
    }
}
